#include "user_config.h"
#include "user_protocol.h"
#include "bsp_led.h"


byte rxBuffer[FRAME_LENGTH];
byte rxIndex = 0;
bool frameStarted = false;


static bool parseProtocolFrame(byte* buffer);
static bool verifyChecksum(ProtocolFrame frame);
static void executeCommand(ProtocolFrame frame);


bool ledState = LOW;     // LED当前状态

/*
*@func:toggle_LED_fastly
*@detail:用于提示功能
*/
void toggle_LED_fastly(uint8_t cnt)
{
    for(int i=0; i<cnt; i++)
    {
        ledState = !ledState;
        digitalWrite(LED_PIN, ledState);
        delay(500);
    }
}


/*
*@func:sendStatusResponse
*@detail:用于命令词“查询状态”后，相应的回复
*@param：address
*/
void sendStatusResponse(byte address) {
  // 构建状态响应帧
  byte response[FRAME_LENGTH];
  
  response[0] = FRAME_HEADER;
  response[1] = address | 0x10;  // 设置方向位为1（语音芯片接收）
  response[2] = 0x04;            // 查询响应命令
  response[3] = 0x00;            // 当前速度
  response[4] = 0x50;            // 当前位置（示例：80%）
  response[5] = 0x00;            // 预留
  response[6] = (response[1] + response[2] + response[3] + response[4] + response[5]) & 0xFF; // 校验和
  response[7] = FRAME_TAIL;
  
  // 发送响应
  Serial.write(response, FRAME_LENGTH);
  //Serial.println("Status response sent");
}


// 命令处理函数
void handleCloseCommand(ProtocolFrame frame) {
  // 执行关盖操作
  //Serial.println("Executing: Close cover command");
  // 这里添加实际的电机控制代码

  toggle_LED_fastly(2);
}

void handleOpenCommand(ProtocolFrame frame) {
  // 执行开盖操作
  //Serial.println("Executing: Open cover command");
  // 这里添加实际的电机控制代码

   toggle_LED_fastly(4);
}

void handleStopCommand(ProtocolFrame frame) {
  // 执行紧急停止
  //Serial.println("Executing: Emergency stop");
  // 这里添加紧急停止代码

   toggle_LED_fastly(6);
}

void handleQueryCommand(ProtocolFrame frame) {
  // 处理状态查询
  //Serial.println("Executing: Status query");
  // 这里可以返回设备状态信息
  //sendStatusResponse(frame.address);

    toggle_LED_fastly(8);
}


/*
*@func:executeCommand
*@detail:将具体的、人能理解的内容，执行对应的指令（并打印出相应的解析结果来）
*/
static void executeCommand(ProtocolFrame frame) {
  // 解析设备地址和方向
  byte device = frame.address & 0x0F;  // 低4位为设备地址
  byte direction = (frame.address >> 4) & 0x01;  // BIT4为方向
  
  Serial.println("=== Protocol Frame Received ===");
  Serial.print("Device: ");
  switch(device) {
    case DEV_TOILET_COVER:
      Serial.print("Toilet Cover");
      break;
    case DEV_WASHER_COVER:
      Serial.print("Washer Cover");
      break;
    default:
      Serial.print("Unknown (0x");
      Serial.print(device, HEX);
      Serial.print(")");
  }
  
  Serial.print(" | Direction: ");
  Serial.println(direction ? "Voice Chip Receive" : "Voice Chip Send");
  
  Serial.print("Command: 0x");
  Serial.print(frame.command, HEX);
  Serial.print(" - ");
  
  // 解析命令字
  switch(frame.command) {
    case CMD_CLOSE:
      Serial.println("Close Cover/Stop");
      handleCloseCommand(frame);
      break;
    case CMD_OPEN:
      Serial.println("Open Cover/Stop");
      handleOpenCommand(frame);
      break;
    case CMD_STOP:
      Serial.println("Emergency Stop");
      handleStopCommand(frame);
      break;
    case CMD_QUERY:
      Serial.println("Query Status");
      handleQueryCommand(frame);
      break;
    default:
      Serial.println("Unknown Command");
  }
  
  // 解析速度数据（如果使用）
  if (frame.speed != 0x00) {
    Serial.print("Speed: Level ");
    Serial.println(frame.speed);
  }
  
  // 解析位置数据（如果使用）
  if (frame.position != 0x00) {
    Serial.print("Target Position: ");
    Serial.print(frame.position);
    Serial.println("%");
  }
  
  Serial.print("Checksum: 0x");
  Serial.print(frame.checksum, HEX);
  Serial.println(" [OK]");
  Serial.println("===============================");
}



/*
*@func:parseProtocolFrame
*@detail:根据已经得到的数据帧，核查校验和，并解析协议：根据已经得到的数据帧，得到命令、位置、速度等详细具体的信息
*@detail:功能由两个子函数实现具体内容
*/
static bool parseProtocolFrame(byte* buffer) {
  ProtocolFrame frame;
  
  // 提取帧数据
  frame.header = buffer[0];
  frame.address = buffer[1];
  frame.command = buffer[2];
  frame.speed = buffer[3];
  frame.position = buffer[4];
  frame.reserved = buffer[5];
  frame.checksum = buffer[6];
  frame.tail = buffer[7];
  
  // 校验和验证
  if (!verifyChecksum(frame)) {
    Serial.println("Checksum error");
    return false;
  }
  
  // 解析并执行命令
  executeCommand(frame);
  return true;
}

/*
*@func:verifyChecksum
*@detail:检查校验和是否合法
*/
static bool verifyChecksum(ProtocolFrame frame) {
  byte calculatedChecksum = (frame.address + frame.command + frame.speed + 
                           frame.position + frame.reserved) & 0xFF;
  return calculatedChecksum == frame.checksum;
}



/*
*@func:processSerialData()
*@detail:处理串口数据(是供外部调用的函数)
*@detail:实现了串口数据的接收，如果串口数据合法，调用了底层的校验、解析和执行函数
*/
void processSerialData() {
  while (Serial.available() > 0) {
    byte incoming = Serial.read();
    
    // 检查帧头
    if (incoming == FRAME_HEADER) {
      frameStarted = true;
      rxIndex = 0;
      rxBuffer[rxIndex++] = incoming;
    } 
    // 如果已经开始接收帧
    else if (frameStarted) {
      rxBuffer[rxIndex++] = incoming;
      
      // 检查是否接收到完整帧
      if (rxIndex >= FRAME_LENGTH) {
        frameStarted = false;
        
        // 验证帧尾
        if (rxBuffer[FRAME_LENGTH - 1] == FRAME_TAIL) {
          // 解析协议帧
          parseProtocolFrame(rxBuffer);
        } else {
          Serial.println("Frame tail error");
        }
        
        // 重置接收状态
        rxIndex = 0;
      }
    }
  }
}
